/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.course.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import lombok.AllArgsConstructor;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.springblade.common.annotation.ServiceLog;
import org.springblade.common.constant.TrainingOperateConstant;
import org.springblade.common.utils.CommonUtil;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.course.bo.CourseBo;
import org.springblade.modules.course.entity.CourseChapterEntity;
import org.springblade.modules.course.entity.CourseChapterSubEntity;
import org.springblade.modules.course.entity.CourseCommentEntity;
import org.springblade.modules.course.excel.CourseExcel;
import org.springblade.modules.course.excel.CourseImporter;
import org.springblade.modules.course.service.CourseCommentService;
import org.springblade.modules.course.service.ICourseChapterService;
import org.springblade.modules.course.service.ICourseChapterSubService;
import org.springblade.modules.course.vo.CourseChapterSubVO;
import org.springblade.modules.course.vo.CourseChapterVO;
import org.springblade.modules.course.vo.CourseCommentVO;
import org.springblade.modules.library.entity.MaterialLibraryEntity;
import org.springblade.modules.library.service.IMaterialLibraryService;
import org.springblade.modules.personal.entity.UserBaseEntity;
import org.springblade.modules.personal.service.IUserBaseService;
import org.springblade.modules.resource.enums.AttachType;
import org.springblade.modules.teaching.entity.CourseChapterSubBankEntity;
import org.springblade.modules.teaching.entity.CourseChapterSubFileEntity;
import org.springblade.modules.teaching.service.ICourseChapterSubBankService;
import org.springblade.modules.teaching.service.ICourseChapterSubFileService;
import org.springblade.modules.teaching.vo.CourseChapterSubBankVO;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.modules.course.entity.CourseEntity;
import org.springblade.modules.course.vo.CourseVO;
import org.springblade.modules.course.service.ICourseService;
import org.springblade.core.boot.ctrl.BladeController;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 课程 控制器
 * @author junxin
 * @since 2023-03-22
 */
@RestController
@AllArgsConstructor
@RequestMapping("blade-course/course")
@Api(value = "课程", tags = "课程接口")
public class CourseController extends BladeController {

	private final ICourseService courseService;
	private final CourseCommentService courseCommentService;
	private final CommonUtil commonUtil;
	private final IUserBaseService userBaseService;
	private final ICourseChapterService courseChapterService;
	private final ICourseChapterSubService courseChapterSubService;
	private final ICourseChapterSubBankService courseChapterSubBankService;
	private final ICourseChapterSubFileService courseChapterSubFileService;
	private final IMaterialLibraryService materialLibraryService;

	/**
	 * 课程 详情
	 */
//	@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入course")
	public R<CourseBo> detail(CourseEntity course) {
		CourseEntity detail = courseService.getOne(Condition.getQueryWrapper(course));
		CourseBo bo=new CourseBo();
		BeanUtil.copyProperties(detail,bo);
		List<CourseChapterEntity> chapterList=courseChapterService.list(Wrappers.<CourseChapterEntity>query()
			.lambda().eq(CourseChapterEntity::getCourseId,detail.getId()).orderByAsc(CourseChapterEntity::getSort));

		//处理章节内容
		if (CollectionUtil.isNotEmpty(chapterList)){
			List<CourseChapterVO> chapterVoist = chapterList.stream().map(chapter -> {
				CourseChapterVO chapterVO = new CourseChapterVO();
				BeanUtil.copyProperties(chapter,chapterVO);

				List<CourseChapterSubEntity> subList = courseChapterSubService.list(Wrappers.<CourseChapterSubEntity>query()
					.lambda().eq(CourseChapterSubEntity::getChapterId, chapter.getId()).orderByAsc(CourseChapterSubEntity::getSort));

				//处理小节内容
				if (CollectionUtil.isNotEmpty(subList)){
					List<CourseChapterSubVO> subVOList = subList.stream().map(sub -> {
						CourseChapterSubVO subVO = new CourseChapterSubVO();
						BeanUtil.copyProperties(sub, subVO);

						CourseChapterSubFileEntity one = courseChapterSubFileService.getOne(Wrappers.<CourseChapterSubFileEntity>query().lambda()
							.eq(CourseChapterSubFileEntity::getSubId, sub.getId()).eq(CourseChapterSubFileEntity::getAttachType, AttachType.COURSE_VEDIO.getCategory())
						);
						if(null!=one)subVO.setSubVedio(one);//学习视频

						subVO.setSubCoursewareList(courseChapterSubFileService.list(Wrappers.<CourseChapterSubFileEntity>query().lambda()
							.eq(CourseChapterSubFileEntity::getSubId,sub.getId()).eq(CourseChapterSubFileEntity::getAttachType, AttachType.COURSE_COURSEWARE.getCategory())));//学习课件

						subVO.setSubQuestionBankList(courseChapterSubBankService.selectSubBankList(sub.getId()));//课后习题
						return subVO;
					}).collect(Collectors.toList());
					chapterVO.setChapterSubList(subVOList);
				}
				return chapterVO;
			}).collect(Collectors.toList());
			bo.setChapterList(chapterVoist);
		}
		return R.data(bo);
	}

	/**
	 * 课程 自定义分页
	 */
//	@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/list")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "分页", notes = "传入course")
	public R<IPage<CourseVO>> page(CourseVO course, Query query) {
		/**
		 * 前台搜索有传保密等级
		 */
		if (null!=course.getSecrecyLevel()) course.setSecrecyLevelSearch(course.getSecrecyLevel());
		/**
		 * 添加保密等级 该用户能看到的保密等级
		 */
		course.setSecrecyLevel(commonUtil.getUserBaseEntity().getSecrecyLevel());
		commonUtil.checkRoleAliasPermission(course,course.getClass());
//		if (!commonUtil.checkRoleAlias(TrainingRoleConstant.Administrator)) course.setCreateUser(AuthUtil.getUserId());
		IPage<CourseVO> pages = courseService.selectCoursePage(Condition.getPage(query), course);
		return R.data(pages);
	}


	/**
	 * 课程 新增
	 */
//	@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@ServiceLog(value = TrainingOperateConstant.COURSE,operate = TrainingOperateConstant.ADD,describe = "新增课程")
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "新增", notes = "传入course")
	public R save(@Valid @RequestBody CourseEntity course) {
		return R.status(courseService.save(course));
	}



	/**
	 * 课程 一键新增
	 */
	@ServiceLog(value = TrainingOperateConstant.COURSE,operate = TrainingOperateConstant.ADD,describe = "一键新增")
	@PostMapping("/save-detail")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "一键新增", notes = "传入课程所有详情条目")
	@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
//	@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	public R saveAll(@Valid @RequestBody CourseBo course) {
		List<CourseChapterVO> chapterList = course.getChapterList();
		if (StringUtils.isNotBlank(course.getTeacherNumber())){
			UserBaseEntity userBaseEntity=userBaseService.getOne(Wrappers.<UserBaseEntity>query().lambda().eq(UserBaseEntity::getUserNumber,course.getTeacherNumber()));
			if (null==userBaseEntity)throw new ServiceException("未找到该编号的用户!");
			course.setTeacherId(userBaseEntity.getUserId());
		}

		if (null==course.getIntegral() || course.getIntegral()<0) course.setIntegral((float)0);
		if (null==course.getPeriod() || course.getPeriod()<0) course.setPeriod(0);
		courseService.saveOrUpdate(course);

		if (CollectionUtil.isNotEmpty(chapterList)){
			chapterList.forEach(chapterNew->{
				//1.章节处理
				chapterNew.setCourseId(course.getId());
				courseChapterService.saveOrUpdate(chapterNew);

				//2.小节处理
				List<CourseChapterSubVO> chapterSubList = chapterNew.getChapterSubList();
				if (CollectionUtil.isEmpty(chapterSubList)) return;
				chapterSubList.forEach(subNew->{
					subNew.setChapterId(chapterNew.getId());
					subNew.setCourseId(course.getId());
					//保存小节
					courseChapterSubService.saveOrUpdate(subNew);

					//学习视频
					if (null!=subNew.getSubVedio()){
						CourseChapterSubFileEntity courseChapterSubFileEntity=new CourseChapterSubFileEntity();
						BeanUtil.copyProperties(subNew.getSubVedio(), courseChapterSubFileEntity, "id");
						courseChapterSubFileEntity.setSubId(subNew.getId());
						courseChapterSubFileEntity.setAttachType(AttachType.COURSE_VEDIO.getCategory());
						courseChapterSubFileService.save(courseChapterSubFileEntity);
						selectByLinkAndUpdateLinkName(subNew.getSubVedio().getLink(),subNew.getSubVedio().getLinkName(), AttachType.COURSE_VEDIO.getCategory());
					}

					// 学习课件
					List<CourseChapterSubFileEntity> subCoursewareList = subNew.getSubCoursewareList();//学习课件
					if (CollectionUtil.isNotEmpty(subCoursewareList)){
						List<CourseChapterSubFileEntity> coursewarelist = subCoursewareList.stream().map(subCourseware -> {
							CourseChapterSubFileEntity CourseChapterSubFileEntity = new CourseChapterSubFileEntity();
							BeanUtil.copyProperties(subCourseware, CourseChapterSubFileEntity, "id");
							CourseChapterSubFileEntity.setSubId(subNew.getId());
							CourseChapterSubFileEntity.setAttachType(AttachType.COURSE_COURSEWARE.getCategory());
							selectByLinkAndUpdateLinkName(subCourseware.getLink(), subCourseware.getLinkName(),AttachType.COURSE_COURSEWARE.getCategory());
							return CourseChapterSubFileEntity;
						}).collect(Collectors.toList());

						courseChapterSubFileService.saveBatch(coursewarelist);
					}

					// 课后习题
					List<CourseChapterSubBankVO> subQuestionBankIdList = subNew.getSubQuestionBankList();//课后习题
					if (CollectionUtil.isNotEmpty(subQuestionBankIdList)){
						List<CourseChapterSubBankEntity> subBankList=new ArrayList<>();
						subQuestionBankIdList.forEach(CourseChapterSubBankVO->{
							CourseChapterSubBankEntity subBankEntity=new CourseChapterSubBankEntity();
							subBankEntity.setSubId(subNew.getId());
							subBankEntity.setConnnectId(CourseChapterSubBankVO.getQuestionId());
							subBankList.add(subBankEntity);
						});
						courseChapterSubBankService.saveBatch(subBankList);
					}

				});

			});
		}
		return R.data(course);
	}

	/**
	 * 一键新增小节资源 ，选择上传资源时，该资源链接没有名称，需要赋上
	 */
	public void selectByLinkAndUpdateLinkName(String link,String linkName,int category){
		MaterialLibraryEntity materialLibraryEntity = materialLibraryService.getOne(Wrappers.<MaterialLibraryEntity>query()
			.lambda().eq(MaterialLibraryEntity::getStoragePath, link));
		if (null!=materialLibraryEntity ){
			if (StringUtils.isNotEmpty(linkName))materialLibraryEntity.setMeterialName(linkName);
			materialLibraryEntity.setStatus(2);
			materialLibraryEntity.setCategory(category);
			materialLibraryService.updateById(materialLibraryEntity);
		}
	}

	/**
	 * 课程 一键修改
	 */
	@ServiceLog(value = TrainingOperateConstant.COURSE,operate = TrainingOperateConstant.UPDATE,describe = "一键修改")
	@PostMapping("/update-detail")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "一键修改", notes = "传入课程所有详情条目")
	@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
//	@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	public R updateAll(@Valid @RequestBody CourseBo course) {
		//流程：把该课程所有条目全部删除  课程、章节、小节  及小节资源 ，然后走新增逻辑
		//1.查出该课程的所有小节
		List<CourseChapterSubEntity> subList = courseChapterSubService.list(Wrappers.<CourseChapterSubEntity>query().lambda().eq(CourseChapterSubEntity::getCourseId, course.getId()));
		if (CollectionUtil.isNotEmpty(subList)){
			List<Long> subIds = subList.stream().map(CourseChapterSubEntity::getId).collect(Collectors.toList());
			courseChapterSubFileService.remove(Wrappers.<CourseChapterSubFileEntity>query().lambda().in(CourseChapterSubFileEntity::getSubId,subIds));
			courseChapterSubBankService.remove(Wrappers.<CourseChapterSubBankEntity>query().lambda().in(CourseChapterSubBankEntity::getSubId,subIds));
		}
		saveAll(course);
		return R.data(course);
	}

	/**
	 * 课程 修改
	 */
	@ServiceLog(value = TrainingOperateConstant.COURSE,operate = TrainingOperateConstant.UPDATE,describe = "修改课程")
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入course")
//	@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	public R update(@Valid @RequestBody CourseEntity course) {
		return R.status(courseService.updateById(course));
	}


	/**
	 * 课程 删除
	 */
	@ServiceLog(value = TrainingOperateConstant.COURSE,operate = TrainingOperateConstant.DELETE,describe = "课程删除")
	@PostMapping("/remove")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
//	@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.status(courseService.deleteLogic(Func.toLongList(ids)));
	}

	/**
	 * 查看课程详情
	 * 该课程下的所有章节、小节 及小节的视频
	 */
//	@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/info")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "课程具体章节和小节", notes = "传入courseId")
	public R<CourseVO> info(Long courseId) {
		CourseVO info = courseService.getCourseInfo(courseId);
		return R.data(info);
	}

	/**
	 * 课程评价 新增
	 */
	@ServiceLog(value = TrainingOperateConstant.COURSE_COMMENT,operate = TrainingOperateConstant.ADD,describe = "新增课程评价")
	@PostMapping("/comment-save")
	@ApiOperationSupport(order = 9)
	@ApiOperation(value = "课程评价新增", notes = "传入courseComment")
	public R courseCommentSave(@Valid @RequestBody CourseCommentEntity courseCommentEntity) {
		return R.status(courseCommentService.save(courseCommentEntity));
	}


	/**
	 * 课程评价 自定义分页
	 */
	@GetMapping("/comment")
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "课程评价分页", notes = "传入course")
	public R<IPage<CourseCommentVO>> courseCommentPage(CourseCommentVO courseCommentVO, Query query) {
		IPage<CourseCommentVO> pages = courseCommentService.selectCourseCommentPage(Condition.getPage(query), courseCommentVO);
		return R.data(pages);
	}


	/**
	 * 课程评价 删除
	 */
	@ServiceLog(value = TrainingOperateConstant.COURSE_COMMENT,operate = TrainingOperateConstant.DELETE,describe = "课程评价删除")
	@PostMapping("/comment-remove")
	@ApiOperationSupport(order = 11)
	@ApiOperation(value = "课程评价逻辑删除", notes = "传入ids")
	public R commentRemove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.status(courseCommentService.deleteLogic(Func.toLongList(ids)));
	}


	/**
	 * 设置老师
	 */
	@GetMapping("/set-teacher")
	@ApiOperationSupport(order = 12)
	@ApiOperation(value = "设置课程的老师", notes = "传入userNumber和课程id")
	public R setTeacher(String userNumber,Long id) {
		UserBaseEntity userBaseEntity=userBaseService.getOne(Wrappers.<UserBaseEntity>query().lambda().eq(UserBaseEntity::getUserNumber,userNumber));
		if (null==userBaseEntity)throw new ServiceException("未找到该编号的用户!");
		CourseEntity courseEntity = courseService.getById(id);
		courseEntity.setTeacherId(userBaseEntity.getUserId());
		return R.data(courseService.updateById(courseEntity));
	}

	/**
	 * 课程下拉接口
	 */
//	@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/select")
	@ApiOperationSupport(order = 12)
	@ApiOperation(value = "课程下拉接口", notes = "")
	public R courseSelect(@ApiIgnore @RequestParam Map<String, Object> entity) {
		QueryWrapper<CourseEntity> queryWrapper = Condition.getQueryWrapper(entity, CourseEntity.class);
		return R.data(courseService.list(queryWrapper));
	}


	/**
	 * 批量导入课程目录
	 */
//	@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("import")
	@ApiOperationSupport(order = 19)
	@ApiOperation(value = "导入课程目录", notes = "传入excel")
	public R importCourse(MultipartFile file) {
		CourseImporter importer = new CourseImporter(courseService,courseChapterService,courseChapterSubService);
		ExcelUtil.save(file, importer, CourseExcel.class);
		return R.success("操作成功");
	}

	/**
	 * 导出模板
	 */
//	@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("export-template")
	@ApiOperationSupport(order = 20)
	@ApiOperation(value = "导出模板")
	public void exportUser(HttpServletResponse response) {
		List<CourseExcel> list = new ArrayList<>();
		ExcelUtil.export(response, "课程目录数据模板", "课程目录数据表", list, CourseExcel.class);
	}

}
